package hu.uszeged.inf.stud.prf.todo.bean.usertask;

import hu.uszeged.inf.stud.prf.todo.dao.resource.ResourceDAO;
import hu.uszeged.inf.stud.prf.todo.dao.task.TaskDAO;
import hu.uszeged.inf.stud.prf.todo.dao.task.TaskTypeDAO;
import hu.uszeged.inf.stud.prf.todo.dao.user.UserDAO;
import hu.uszeged.inf.stud.prf.todo.dao.usertask.UserTaskDAO;
import hu.uszeged.inf.stud.prf.todo.entity.resource.Resource;
import hu.uszeged.inf.stud.prf.todo.entity.task.Task;
import hu.uszeged.inf.stud.prf.todo.entity.task.TaskType;
import hu.uszeged.inf.stud.prf.todo.entity.user.User;
import hu.uszeged.inf.stud.prf.todo.entity.usertask.UserTask;

import java.util.ArrayList;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.inject.Inject;

import org.primefaces.model.DualListModel;

@ManagedBean
@ViewScoped
public class UserTaskBean {
	
	@Inject
	private UserTaskDAO usertaskDAO;

	@Inject
	private ResourceDAO resourceDAO;

	@Inject
	private TaskDAO taskDAO;
	
	@Inject
	private TaskTypeDAO taskTypeDAO;
	
	@Inject
	private UserDAO userDAO;
	
	private Long id;
	
	private UserTask usertask;
	
    private DualListModel<Resource> resources;
    private DualListModel<TaskType> taskTypes;
    private DualListModel<User> users;
    
    public DualListModel<Resource> getResources() {
        return resources;  
    }
    
    public void setResources(DualListModel<Resource> resources) {
        ArrayList<Resource> resList = new ArrayList<Resource>();
    	for (int i=0; i<resources.getTarget().size(); ++i) {
    		Object res = resources.getTarget().get(i);
        	resList.add( resourceDAO.getResourceByName(res.toString(), usertask.getUser()) );
        }
        this.resources.setTarget(resList);
    }
     
    public DualListModel<TaskType> getTaskTypes() {
        return taskTypes;  
    }
    
    public void setTaskTypes(DualListModel<TaskType> taskTypes) {
    	ArrayList<TaskType> taskTypeList = new ArrayList<TaskType>();
    	for (int i=0; i<taskTypes.getTarget().size(); ++i) {
    		Object taskType = taskTypes.getTarget().get(i);
        	taskTypeList.add( taskTypeDAO.getTaskTypeByName(taskType.toString(), usertask.getUser()) );
        }
        this.taskTypes.setTarget(taskTypeList);
    }

	public DualListModel<User> getUsers() {
		return users;
	}

	public void setUsers(DualListModel<User> users) {
		ArrayList<User> userList = new ArrayList<User>();
    	for (int i=0; i<users.getTarget().size(); ++i) {
    		Object user = users.getTarget().get(i);
        	userList.add( userDAO.getUserByName(user.toString()) );
        }
		ArrayList<User> userListSource = new ArrayList<User>();
    	for (int i=0; i<users.getSource().size(); ++i) {
    		Object user = users.getSource().get(i);
        	userListSource.add( userDAO.getUserByName(user.toString()) );
        }
        this.users.setSource(userListSource);
        this.users.setTarget(userList);
	}
	
	public void load(User user) {
        if (null == id) {
			usertask = new UserTask();
		} else {
			usertask = usertaskDAO.findById(id, false);
		}

        List<Resource> resourcesSource;
		List<Resource> resourcesTarget = new ArrayList<Resource>();
		List<TaskType> taskTypesSource;
		List<TaskType> taskTypesTarget = new ArrayList<TaskType>();
		List<User> usersSource;
        List<User> usersTarget = new ArrayList<User>();

		if (usertask.getUser()==null) {
			usertask.setUser(user);
		}
		
		resourcesSource = resourceDAO.getResourcesForUser(usertask.getUser());
		taskTypesSource = taskTypeDAO.getTaskTypesForUser(usertask.getUser());
        usersSource = userDAO.getOtherUsers(usertask.getUser());
		
		if (usertask.getTask()==null) {
			usertask.setTask(new Task());
		} else {
			if (usertask.getTask().getResources() != null) {
				for (Resource res : usertask.getTask().getResources()) {
					if (!res.isArchive()) {
			        	resourcesTarget.add(res);
					}
				}
	        }

	        if (usertask.getTasktypes() != null) {
	        	for (TaskType tt : usertask.getTasktypes()) {
					if (!tt.isArchive()) {
			        	taskTypesTarget.add(tt);
					}
				}
	        }

	        if (usertask.getTask().getUserTasks() != null) {
	        	for(UserTask userTask : usertask.getTask().getUserTasks()) {
	        		if (!userTask.isArchive()) {
	        			usersTarget.add(userTask.getUser());
	        		}
	        	}
	        }
	        usersTarget.remove(usertask.getUser());
		}
	    
        resourcesSource.removeAll(resourcesTarget);
        resources = new DualListModel<Resource>(resourcesSource, resourcesTarget);
        
        taskTypesSource.removeAll(taskTypesTarget);
        taskTypes = new DualListModel<TaskType>(taskTypesSource, taskTypesTarget);

        usersSource.removeAll(usersTarget);
        users = new DualListModel<User>(usersSource, usersTarget);
	}
	
	public String save() {
		usertask.getTask().setResources(resources.getTarget());
		usertask.setTasktypes(taskTypes.getTarget());
		for(User user : users.getTarget()) {
			List<UserTask> userTasks = user.getUserTasks();
			if(userTasks != null) {
				UserTask hasTask = null;
				for (UserTask ut : userTasks) {
					if (ut.getTask().equals(usertask.getTask())) {
						hasTask = ut;
						break;
					}
				}
				if (hasTask == null) {
					UserTask newCollab = new UserTask(user, usertask);
					usertaskDAO.makePersistent(newCollab);
				} else {
					usertaskDAO.merge(hasTask);
				}
			}
		}
		for(User user : users.getSource()) {
			if(!users.getTarget().contains(user)) {
				List<UserTask> userTasks = user.getUserTasks();
				if(userTasks != null) {
					UserTask hasTask = null;
					for (UserTask ut : userTasks) {
						if (ut.getTask().equals(usertask.getTask())) {
							hasTask = ut;
							break;
						}
					}
					if (hasTask != null) {
						hasTask.setArchive(true);
						usertaskDAO.merge(hasTask);
					}
				}
			}
		}
		try {
			taskDAO.makePersistent(usertask.getTask());
			taskDAO.flush();
			usertaskDAO.makePersistent(usertask);
			usertaskDAO.flush();
		} catch (Exception e){
			taskDAO.merge(usertask.getTask());
			taskDAO.flush();
			usertaskDAO.merge(usertask);
			usertaskDAO.flush();
		}
		return "/content/usertask/list?faces-redirect=true";
	}
	
	public String remove() {
		usertask.setArchive(true);
		usertaskDAO.merge(usertask);
		usertaskDAO.flush();
		return "/content/usertask/list?faces-redirect=true";
	}
	
	public Long getId() {
		return id;
	}
	
	public void setId(Long id) {
		this.id = id;
	}
	
	public UserTask getUserTask() {
		return usertask;
	}
	
	public void setUserTask(UserTask usertask) {
		this.usertask = usertask;
	}

}
